package com.ourteam.system.api;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.ArrayUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ourteam.frame.controller.AbstractServiceController;
import com.ourteam.frame.web.AbstractSearchHelper;
import com.ourteam.frame.web.AbstractStaticArraySearchHelper;
import com.ourteam.frame.web.AbstractTreeBuilderHelper;
import com.ourteam.frame.web.ApplicationModel;
import com.ourteam.frame.web.GridBean;
import com.ourteam.frame.web.TreeParamModel;
import com.ourteam.frame.web.TreeViewNodeBean;
import com.ourteam.system.dao.ISysDomainDAO;
import com.ourteam.system.dao.ISysModuleDAO;
import com.ourteam.system.dao.SysActionDAOQueryBean;
import com.ourteam.system.dao.SysDomainDAOQueryBean;
import com.ourteam.system.dao.SysEventLogDAOQueryBean;
import com.ourteam.system.dao.SysModuleDAOQueryBean;
import com.ourteam.system.domain.ApplicationDomain;
import com.ourteam.system.domain.SystemAction;
import com.ourteam.system.domain.SystemModule;
import com.ourteam.system.domain.SystemProperty;
import com.ourteam.system.service.ISystemApplicationService;
import com.ourteam.system.service.ISystemEventLogService;

@Controller
@CrossOrigin
@RequestMapping("/api/SYSTEM/APP")
public class SystemAppAPI extends AbstractServiceController {

	@Autowired
	private ISystemApplicationService systemApplicationService;

	@Autowired
	private ISystemEventLogService systemEventLogService;

	@RequestMapping("/getSystemDomain")
	@ResponseBody
	public ApplicationDomain[] getSystemDomain(
			@RequestParam(value = "excludeIds[]", required = false) long[] excludeIds, HttpServletRequest request,
			Model model) throws Exception {

		SysDomainDAOQueryBean queryBean = new SysDomainDAOQueryBean();

		queryBean.setSortProperty(ISysDomainDAO.SortIndex);

		if (ArrayUtils.isNotEmpty(excludeIds)) {
			queryBean.createCriteria().andIdNotIn(excludeIds);
		}

		return systemApplicationService.queryApplicationDomains(queryBean);

	}

	@RequestMapping("/getSysDomainById")
	@ResponseBody
	public ApplicationDomain getSysDomainById(@RequestParam(value = "id", required = true) long id,
			HttpServletRequest request, Model model) throws Exception {

		return systemApplicationService.getApplicationDomainById(id);

	}

	@RequestMapping("/getSysModuleById")
	@ResponseBody
	public SystemModule getSysModuleById(@RequestParam(value = "id", required = true) long id,
			HttpServletRequest request, Model model) throws Exception {

		return systemApplicationService.getSystemModuleById(id);

	}

	@RequestMapping("/getSysActionById")
	@ResponseBody
	public SystemAction getSysActionById(@RequestParam(value = "id", required = true) long id,
			HttpServletRequest request, Model model) throws Exception {

		return systemApplicationService.getSystemActionById(id);

	}

	@RequestMapping("/getSysActionByModuleId")
	@ResponseBody
	public GridBean getSysActionByModuleId(
			@RequestParam(value = "moduleId", required = false, defaultValue = "0") long id, HttpServletRequest request,
			Model model) throws Exception {

		SystemActionSearchModel actionSearchModel = new SystemActionSearchModel();

		actionSearchModel.setSysModuleId(id);

		AbstractStaticArraySearchHelper<SysActionDAOQueryBean, SystemActionSearchModel> searchHelper = new AbstractStaticArraySearchHelper<SysActionDAOQueryBean, SystemActionSearchModel>(
				actionSearchModel) {

			@Override
			protected SysActionDAOQueryBean createQueryBean() {
				return new SysActionDAOQueryBean();
			}

			@Override
			protected Object[] getData(SystemActionSearchModel searchModel) throws Exception {
				return systemApplicationService.getSystemActions(searchModel.getSysModuleId());
			}
		};

		return searchHelper.doSearch(request);

	}

	@RequestMapping("/getSysDomainModules")
	@ResponseBody
	public GridBean getSysDomainModules(@RequestParam final long domainId,
			@ModelAttribute TreeParamModel treeParamModel) throws Exception {

		SystemAppModuleTreeBuilder treeBuilder = new SystemAppModuleTreeBuilder(0);

		AbstractTreeBuilderHelper<SystemAppModuleTreeBuilder> treeBuilderHelper = new AbstractTreeBuilderHelper<SystemAppModuleTreeBuilder>(
				treeBuilder) {

			@Override
			protected Object getInitParameter() {
				return String.valueOf(domainId);
			}

		};

		return treeBuilderHelper.buildTree(treeParamModel);
	}

	@RequestMapping("/querySysDomainList")
	@ResponseBody
	public GridBean querySysDomains(final @ModelAttribute SystemDomainSearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {

		AbstractSearchHelper<SysDomainDAOQueryBean, SystemDomainSearchModel> searchHelper = new AbstractSearchHelper<SysDomainDAOQueryBean, SystemDomainSearchModel>(
				searchModel) {

			@Override
			protected int queryCount(SysDomainDAOQueryBean queryBean) throws Exception {
				return systemApplicationService.queryApplicationDomainCount(queryBean);
			}

			@Override
			protected Object[] queryData(SysDomainDAOQueryBean queryBean) throws Exception {
				return systemApplicationService.queryApplicationDomains(queryBean);
			}

			@Override
			protected SysDomainDAOQueryBean createQueryBean() {
				return new SysDomainDAOQueryBean();
			}

		};

		return searchHelper.doSearch(request);

	}

	@RequestMapping("/saveSysDomain")
	@ResponseBody
	public ApplicationDomain saveSysDomain(@ModelAttribute ApplicationDomain applicationDomain,
			HttpServletRequest request, Model model) throws Exception {

		if (applicationDomain.getId() != 0) {
			systemApplicationService.modifyApplicationDomain(applicationDomain);
		} else {
			systemApplicationService.createApplicationDomain(applicationDomain);
		}

		return applicationDomain;
	}

	@RequestMapping("/deleteSysDomain")
	@ResponseBody
	public String deleteSysDomains(@RequestParam(value = "ids[]") long[] ids, HttpServletRequest request, Model model)
			throws Exception {

		for (int i = 0; i < ids.length; i++) {
			systemApplicationService.deleteApplicationDomain(ids[i]);
		}

		return "success";
	}

	@RequestMapping("/getSystemModuleTreeSelect")
	@ResponseBody
	public TreeViewNodeBean[] getSystemModuleTreeSelect(@RequestParam(value = "domainId") long domainId,
			@RequestParam(value = "disabledIds[]", required = false) long[] disabledIds) throws Exception {

		List<TreeViewNodeBean> treeNodeBeans = new ArrayList<TreeViewNodeBean>();

		SysModuleDAOQueryBean queryBean = new SysModuleDAOQueryBean();

		queryBean.createCriteria().andDomainIdEqualTo(domainId).andParentModuleIdEqualTo(0);

		queryBean.setSortProperty(ISysModuleDAO.SortIndex);

		SystemModule[] modules = this.systemApplicationService.querySystemModules(queryBean);

		for (int i = 0; i < modules.length; i++) {

			SystemModule module = modules[i];

			TreeViewNodeBean nodeBean = new TreeViewNodeBean();

			nodeBean.setNodeData(module);

			nodeBean.setId(String.valueOf(module.getId()));

			nodeBean.setText(module.getModuleName());

			nodeBean.setIcon(module.getModuleIcon());

			if (ArrayUtils.isNotEmpty(disabledIds)) {
				nodeBean.setDisabled(ArrayUtils.contains(disabledIds, module.getId()));
			}

			getSystemModules(domainId, module.getId(), nodeBean, disabledIds);

			treeNodeBeans.add(nodeBean);
		}

		return treeNodeBeans.toArray(new TreeViewNodeBean[treeNodeBeans.size()]);
	}

	protected void getSystemModules(long domainId, long parentModuleId, TreeViewNodeBean treeNodeBean,
			long[] disabledIds) throws Exception {

		SysModuleDAOQueryBean queryBean = new SysModuleDAOQueryBean();

		queryBean.createCriteria().andDomainIdEqualTo(domainId).andParentModuleIdEqualTo(parentModuleId);

		queryBean.setSortProperty(ISysModuleDAO.SortIndex);

		SystemModule[] systemModules = this.systemApplicationService.querySystemModules(queryBean);

		List<TreeViewNodeBean> children = new ArrayList<>();

		for (int i = 0; i < systemModules.length; i++) {

			SystemModule module = systemModules[i];

			TreeViewNodeBean nodeBean = new TreeViewNodeBean();

			nodeBean.setNodeData(module);

			nodeBean.setId(String.valueOf(module.getId()));

			nodeBean.setText(module.getModuleName());

			nodeBean.setIcon(module.getModuleIcon());

			if (ArrayUtils.isNotEmpty(disabledIds)) {
				nodeBean.setDisabled(ArrayUtils.contains(disabledIds, module.getId()));
			}

			if (treeNodeBean.isDisabled()) {
				nodeBean.setDisabled(treeNodeBean.isDisabled());
			}

			getSystemModules(domainId, module.getId(), nodeBean, disabledIds);

			children.add(nodeBean);
		}

		treeNodeBean.setNodes(children.toArray(new TreeViewNodeBean[children.size()]));

	}

	@RequestMapping("/saveSysModule")
	@ResponseBody
	public SystemModule saveSysModule(@RequestParam(value = "domainId") long domainId,
			@ModelAttribute SystemModule systemModule, HttpServletRequest request, Model model) throws Exception {

		systemModule.setDomainId(domainId);

		if (systemModule.getId() != 0) {
			systemApplicationService.modifySystemModule(systemModule);
		} else {
			systemApplicationService.createSystemModule(systemModule);
		}

		return systemModule;
	}

	@RequestMapping("/deleteSysModule")
	@ResponseBody
	public String deleteSysModule(@RequestParam(value = "id") long id, HttpServletRequest request, Model model)
			throws Exception {

		this.systemApplicationService.deleteSystemModule(id);

		return "success";
	}

	@RequestMapping("/deleteSysAction")
	@ResponseBody
	public String deleteSysAction(@RequestParam(value = "ids") long[] ids, HttpServletRequest request, Model model)
			throws Exception {

		for (int i = 0; i < ids.length; i++) {
			this.systemApplicationService.deleteSystemAction(ids[i]);
		}

		return "success";
	}

	@RequestMapping("/saveSysAction")
	@ResponseBody
	public SystemAction saveSysAction(@RequestParam(value = "domainId") long domainId,
			@ModelAttribute SystemAction systemAction, HttpServletRequest request, Model model) throws Exception {

		systemAction.setDomainId(domainId);

		if (systemAction.getId() != 0) {
			systemApplicationService.modifySystemAction(systemAction);
		} else {
			systemApplicationService.createSystemAction(systemAction);
		}

		return systemAction;
	}

	@RequestMapping("/moveUpSysDoamin")
	@ResponseBody
	public String moveUpSysDoamin(@RequestParam(value = "domainId") long domainId, HttpServletRequest request,
			Model model) throws Exception {

		ApplicationDomain applicationDomain = systemApplicationService.getApplicationDomainById(domainId);

		if (applicationDomain.getSort() > 1) {
			systemApplicationService.setSysDomainSortIndex(domainId, applicationDomain.getSort() - 1);
		}

		return "success";
	}

	@RequestMapping("/moveDownSysDoamin")
	@ResponseBody
	public String moveDownSysDoamin(@RequestParam(value = "domainId") long domainId, HttpServletRequest request,
			Model model) throws Exception {

		ApplicationDomain applicationDomain = systemApplicationService.getApplicationDomainById(domainId);

		int totalCount = systemApplicationService.queryApplicationDomainCount(null);

		if (applicationDomain.getSort() < totalCount) {
			systemApplicationService.setSysDomainSortIndex(domainId, applicationDomain.getSort() + 1);
		}

		return "success";
	}

	@RequestMapping("/setSysDoaminSort")
	@ResponseBody
	public String setSysDoaminSort(@RequestParam(value = "domainId") long domainId, @RequestParam int sortIndex)
			throws Exception {

		systemApplicationService.setSysDomainSortIndex(domainId, sortIndex);

		return "success";

	}

	@RequestMapping("/moveUpSysModule")
	@ResponseBody
	public String moveUpSysModule(@RequestParam(value = "sysModuleId") long moduleId, HttpServletRequest request,
			Model model) throws Exception {

		SystemModule systemModule = systemApplicationService.getSystemModuleById(moduleId);

		if (systemModule.getSortIndex() > 1) {
			systemApplicationService.setSysModuleSortIndex(moduleId, systemModule.getSortIndex() - 1);
		}

		return "success";
	}

	@RequestMapping("/moveDownSysModule")
	@ResponseBody
	public String moveDownSysModule(@RequestParam(value = "sysModuleId") long moduleId, HttpServletRequest request,
			Model model) throws Exception {

		SystemModule systemModule = systemApplicationService.getSystemModuleById(moduleId);

		int totalCount = systemApplicationService.getMaxSystemModuleSort(systemModule.getDomainId(),
				systemModule.getParentModuleId());

		if (systemModule.getSortIndex() < totalCount) {
			systemApplicationService.setSysModuleSortIndex(moduleId, systemModule.getSortIndex() + 1);
		}

		return "success";
	}

	@RequestMapping("/querySysEventLogs")
	@ResponseBody
	public GridBean querySysEventLogs(final @ModelAttribute SystemEventLogSearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {

		AbstractSearchHelper<SysEventLogDAOQueryBean, SystemEventLogSearchModel> searchHelper = new AbstractSearchHelper<SysEventLogDAOQueryBean, SystemEventLogSearchModel>(
				searchModel) {

			@Override
			protected int queryCount(SysEventLogDAOQueryBean queryBean) throws Exception {
				return systemEventLogService.querySystemEventLogCount(queryBean);
			}

			@Override
			protected Object[] queryData(SysEventLogDAOQueryBean queryBean) throws Exception {
				return systemEventLogService.querySystemEventLog(queryBean);
			}

			@Override
			protected SysEventLogDAOQueryBean createQueryBean() {
				return new SysEventLogDAOQueryBean();
			}

		};

		return searchHelper.doSearch(request);

	}

	@RequestMapping("/saveSystemConfig/{configType}")
	@ResponseBody
	public Map<String, String> saveSystemConfig(@PathVariable String configType,
			@RequestParam Map<String, String> configMap) throws Exception {

		Subject subject = SecurityUtils.getSubject();

		ApplicationModel appModel = (ApplicationModel) subject.getPrincipal();

		SystemProperty[] systemProperties = this.systemApplicationService.getSystemPropertiesByCatalog(configType);

		List<String> propertyCodeList = new ArrayList<>();

		for (int i = 0; i < systemProperties.length; i++) {
			propertyCodeList.add(systemProperties[i].getPropertyCode());
			if (configMap.containsKey(systemProperties[i].getPropertyCode())) {
				systemProperties[i].setPropertyValue(configMap.get(systemProperties[i].getPropertyCode()));
				this.systemApplicationService.modifySystemProperty(systemProperties[i]);
			}
		}

		for (Iterator<String> iterator = configMap.keySet().iterator(); iterator.hasNext();) {
			String propertyCode = iterator.next();
			if (propertyCodeList.contains(propertyCode) == false) {
				SystemProperty systemProperty = new SystemProperty();

				systemProperty.setPropertyCatalog(configType);
				systemProperty.setPropertyCode(propertyCode);
				systemProperty.setPropertyValue(configMap.get(propertyCode));
				this.systemApplicationService.createNewSystemProperty(systemProperty);
			}
		}

		systemProperties = this.systemApplicationService.getSystemPropertiesByCatalog(configType);

		for (int i = 0; i < systemProperties.length; i++) {
			appModel.getAppConfigMap().put(systemProperties[i].getPropertyCode(),
					systemProperties[i].getPropertyValue());
		}

		return configMap;

	}

	@RequestMapping("/getSystemConfig")
	@ResponseBody
	public Map<String, String> getSystemConfig(@RequestParam String configType) throws Exception {
		SystemProperty[] systemProperties = this.systemApplicationService.getSystemPropertiesByCatalog(configType);

		Map<String, String> map = new HashMap<String, String>();

		for (int i = 0; i < systemProperties.length; i++) {
			map.put(systemProperties[i].getPropertyCode(), systemProperties[i].getPropertyValue());
		}

		return map;

	}

}
